package com.wty.design.creational.singleton;

/**
 * @Author wangtengyu
 * @Create 2018-09-18-10:19
 * 同步的懒汉式，效率低
 */
public class DoubleCheckSingleton {
    private static DoubleCheckSingleton instance = null;
    private static boolean flag=true;

    //单例模式一定要把无参构造私有化
    private DoubleCheckSingleton() {

        if (flag){
            //如果flag为true，说明没实例化对象，可以实例化，实例化之后更新只
            flag=!flag;
        }else{
            throw new RuntimeException("单例构造器禁止反射");
        }
//        if (instance!=null){
//            throw new RuntimeException("单例构造器禁止反射");
//        }
    }
    public static DoubleCheckSingleton getInstance() {
        if (instance == null) {
            //第一次竞争的时候好几个线程会进入这里，之后的话就不会有竞争锁的开销了
            synchronized (DoubleCheckSingleton.class){
                //第一次竞争尝试获取锁的线程都会进入这里，因此多了一次判断
                if (instance==null){
                    instance = new DoubleCheckSingleton();
                    /*
                        指令重排序问题
                        instance = new DoubleCheckSingleton();实际分为3步
                        1.在内存中分配空间
                        2.初始化对象
                        3.instance指向分配的内存空间
                        但是因为指令的重排序，可能2和3的顺序互换。
                        instance指向了内存空间时，对象还未初始化完成。所以instance虽然不等于null，但是并不会实际调用任何对象。
                     */
                }
            }
        }
        return instance;
    }
}
